using System;
using System.Collections.Generic;
using System.Text;

namespace OracleInternal.I18N
{
	internal class UTF16ConvAL16UTF16LE : Conv
	{
		public override int MinBytesPerChar => 2;

		public override int MaxBytesPerChar => 2;

		internal UTF16ConvAL16UTF16LE(int oracleId)
			: base(oracleId)
		{
		}

		public override int ConvertBytesToChars(byte[] bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, bool ccb)
		{
			int num = offset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num + count;
			if (num2 > bytes.Length)
			{
				num2 = bytes.Length;
			}
			int num3 = charOffset;
			if (num3 < 0)
			{
				num3 = 0;
			}
			int num4 = num3 + charCount;
			if (num4 > chars.Length)
			{
				num4 = chars.Length;
			}
			int num5 = num3;
			while (num5 < num4 && num + 1 < num2)
			{
				if (num + 1 >= num2)
				{
					if (ccb)
					{
						break;
					}
					throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
				}
				char c = (char)((bytes[num + 1] << 8) + bytes[num]);
				if (UTF16ConvUtility.IsHiSurrogate(c))
				{
					if (num + 3 >= num2)
					{
						if (ccb)
						{
							break;
						}
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					if (num5 + 1 >= num4)
					{
						break;
					}
					num += 2;
					char c2 = (char)((bytes[num + 1] << 8) + bytes[num]);
					if (UTF16ConvUtility.IsLoSurrogate(c2))
					{
						chars[num5++] = c;
					}
					else
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						chars[num5++] = '\ufffd';
					}
					chars[num5++] = c2;
				}
				else
				{
					chars[num5++] = c;
				}
				num += 2;
			}
			charCount = num5 - charOffset;
			return num - offset;
		}

		public override int ConvertCharsToBytes(char[] chars, int charsOffset, int nchars, byte[] bytes, int byteOffset, ref int byteCount, bool bUseReplacementChar)
		{
			int i = charsOffset;
			if (i < 0)
			{
				i = 0;
			}
			int num = byteOffset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = charsOffset + nchars;
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			for (; i < num2; i++)
			{
				if (num + 1 >= num3)
				{
					break;
				}
				bytes[num + 1] = (byte)((int)chars[i] >> 8);
				bytes[num] = (byte)(chars[i] & 0xFFu);
				num += 2;
			}
			byteCount = num - byteOffset;
			return i - charsOffset;
		}

		public override int ConvertStringToBytes(string chars, int charsOffset, int nchars, byte[] bytes, int byteOffset, ref int byteCount, bool bUseReplacementChar)
		{
			int i = charsOffset;
			if (i < 0)
			{
				i = 0;
			}
			int num = byteOffset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = i + nchars;
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			int num3 = num + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			for (; i < num2; i++)
			{
				if (num + 1 >= num3)
				{
					break;
				}
				bytes[num + 1] = (byte)((int)chars[i] >> 8);
				bytes[num] = (byte)(chars[i] & 0xFFu);
				num += 2;
			}
			byteCount = num - byteOffset;
			return i - charsOffset;
		}

		public override int ConvertBytesToChars(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount, char[] chars, int charOffset, ref int charCount, bool bUseReplacementChar)
		{
			int num = charOffset;
			int charCount2 = charCount;
			int num2 = 0;
			int num3 = 0;
			int continuationOffset = 0;
			byte[] array = null;
			int byteCount = 0;
			int idx = 0;
			int offSet = bytes[0].Offset;
			bool flag = false;
			if (bytesOffset > 0)
			{
				UTF16ConvUtility.GetSegementIndices(bytes, bytesOffset, ref idx, ref offSet);
			}
			for (int i = idx; i < bytes.Count; i++)
			{
				if (flag)
				{
					break;
				}
				if (charCount2 <= 0)
				{
					break;
				}
				int num4 = bytes[i].Offset + continuationOffset;
				int num5 = bytes[i].Count - continuationOffset;
				if (i == idx)
				{
					num4 = offSet + continuationOffset;
					num5 = bytes[i].Count - (offSet - bytes[i].Offset) - continuationOffset;
				}
				if (bytesCount - num3 <= num5)
				{
					num5 = bytesCount - num3;
					flag = true;
				}
				int num6 = ConvertBytesToChars(bytes[i].Array, num4, num5, chars, num, ref charCount2, bUseReplacementChar);
				num3 += num6;
				num += charCount2;
				num2 += charCount2;
				charCount2 = charCount - num2;
				if (charCount2 > 0 && num6 < num5 && !flag && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[4];
					}
					byte[] array2 = bytes[i + 1].Array;
					int num7 = num4 + num6;
					byte b = bytes[i].Array[num7];
					bool flag2 = UTF16ConvUtility.IsHiSurrogate((char)(array2[0] << 8));
					int buffer1Bytes = num5 - num6;
					if (!flag2)
					{
						array[0] = b;
						array[1] = array2[bytes[i + 1].Offset];
						continuationOffset = 1;
						byteCount = 2;
					}
					else if (flag2)
					{
						UTF16ConvUtility.GetRemainingBytes(4, bytes[i].Array, num7, buffer1Bytes, bytes, ref i, ref continuationOffset, array);
						byteCount = 4;
					}
					num6 = ConvertBytesToChars(array, 0, byteCount, chars, num, ref charCount2, bUseReplacementChar);
					if (num6 == 0)
					{
						break;
					}
					num3 += num6;
					num += charCount2;
					num2 += charCount2;
					charCount2 = charCount - num2;
				}
				else
				{
					continuationOffset = 0;
				}
			}
			charCount = num2;
			return num3;
		}

		public override int ConvertBytesToUTF16(byte[] bytes, int byteOffset, int byteCount, byte[] utf16Bytes, int utf16BytesOffset, ref int utf16BytesCount, bool bUseReplacementChar)
		{
			int num = byteOffset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num + byteCount;
			if (num2 > bytes.Length)
			{
				num2 = bytes.Length;
			}
			int num3 = utf16BytesOffset;
			if (num3 < 0)
			{
				num3 = 0;
			}
			int num4 = num3 + utf16BytesCount;
			if (num4 > utf16Bytes.Length)
			{
				num4 = utf16Bytes.Length;
			}
			while (num < num2 && num3 < num4)
			{
				utf16Bytes[num3++] = bytes[num++];
			}
			utf16BytesCount = num3 - utf16BytesOffset;
			return num - byteOffset;
		}

		public override int ConvertUTF16ToBytes(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount, byte[] bytes, int byteOffset, ref int byteCount, bool bUseReplacementChar = true)
		{
			return ConvertBytesToUTF16(utf16Bytes, utf16BytesOffset, utf16BytesCount, bytes, byteOffset, ref byteCount, bUseReplacementChar);
		}

		public override int GetCharsLength(byte[] bytes, int byteOffset, int byteCount)
		{
			if (byteOffset + byteCount > bytes.Length)
			{
				return (bytes.Length - byteOffset) / 2;
			}
			return byteCount / 2;
		}

		public override int GetCharsLength(ArraySegment<byte> bytes, int bytesOffset, int bytesCount)
		{
			if (bytesCount > bytes.Count)
			{
				return (bytes.Count - bytesOffset) / 2;
			}
			return bytesCount / 2;
		}

		public override int GetCharsLength(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount)
		{
			return bytesCount / 2;
		}

		public override int GetBytesLength(char[] chars, int charOffset, int charCount)
		{
			if (charOffset + charCount > chars.Length)
			{
				return (chars.Length - charOffset) * 2;
			}
			return 2 * charCount;
		}

		public override int GetBytesLength(string str, int strOffset, int strCount)
		{
			if (strOffset + strCount > str.Length)
			{
				return (str.Length - strOffset) * 2;
			}
			return 2 * strCount;
		}

		public override int GetBytesLength(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount)
		{
			if (utf16BytesOffset + utf16BytesCount > utf16Bytes.Length)
			{
				return utf16Bytes.Length - utf16BytesOffset;
			}
			return utf16BytesCount;
		}

		public override int GetBytesOffset(byte[] bytes, int byteOffset, int byteCount, int charCount)
		{
			return charCount * 2;
		}

		public override int GetBytesOffset(IList<ArraySegment<byte>> bytes, int charCount)
		{
			return charCount * 2;
		}
	}
}
